package com.macro.mall.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.github.pagehelper.PageHelper;
import com.macro.mall.bo.AdminUserDetails;
import com.macro.mall.dao.UmsAdminPermissionRelationDao;
import com.macro.mall.dao.UmsAdminRoleRelationDao;
import com.macro.mall.dto.UmsAdminParam;
import com.macro.mall.dto.UpdateAdminPasswordParam;
import com.macro.mall.mapper.UmsAdminMapper;
import com.macro.mall.mapper.UmsAdminPermissionRelationMapper;
import com.macro.mall.mapper.UmsAdminRoleRelationMapper;
import com.macro.mall.model.UmsAdmin;
import com.macro.mall.model.UmsAdminExample;
import com.macro.mall.model.UmsAdminPermissionRelation;
import com.macro.mall.model.UmsAdminPermissionRelationExample;
import com.macro.mall.model.UmsAdminRoleRelation;
import com.macro.mall.model.UmsAdminRoleRelationExample;
import com.macro.mall.model.UmsPermission;
import com.macro.mall.model.UmsResource;
import com.macro.mall.model.UmsRole;
import com.macro.mall.security.util.JwtTokenUtil;
import com.macro.mall.service.UmsAdminService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author Administrator
 * @date 2020/6/1
 * @since
 */
@Service
public class UmsAdminServiceImpl implements UmsAdminService {
	private static final Logger LOGGER = LoggerFactory.getLogger(UmsAdminServiceImpl.class);
	@Autowired
	private UmsAdminMapper adminMapper;

	@Autowired
	private JwtTokenUtil jwtTokenUtil;

	@Autowired
	private UmsAdminRoleRelationDao adminRoleRelationDao;
	@Autowired
	private UmsAdminPermissionRelationMapper adminPermissionRelationMapper;
	@Autowired
	private UmsAdminPermissionRelationDao adminPermissionRelationDao;
	@Autowired
	private UmsAdminRoleRelationMapper adminRoleRelationMapper;

	@Autowired
	private PasswordEncoder passwordEncoder;
	@Override
	public UmsAdmin register(UmsAdminParam umsAdminParam) {
		UmsAdmin umsAdmin = new UmsAdmin();
		BeanUtils.copyProperties(umsAdminParam,umsAdmin);
		umsAdmin.setCreateTime(new Date());
		umsAdmin.setStatus(1);
		//查询是否存在相同用户名的用户
		UmsAdminExample example = new UmsAdminExample();
		example.createCriteria().andUsernameEqualTo(umsAdmin.getUsername());
		List<UmsAdmin> umsAdmins = adminMapper.selectByExample(example);
		if(umsAdmins.size()>0){
			return null;
		}
		//将用户密码 进行加密
		String encode = passwordEncoder.encode(umsAdmin.getPassword());
		umsAdmin.setPassword(encode);
		adminMapper.insert(umsAdmin);
		return umsAdmin;
	}

	@Override
	public String login(String username, String password) {
		String token = null;
		try {
			UserDetails userDetails = loadUserByUsername(username);
			if(!passwordEncoder.matches(password,userDetails.getPassword())){
				throw new BadCredentialsException("密码不正确");
			}
			UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
			SecurityContextHolder.getContext().setAuthentication(authentication);
			token = jwtTokenUtil.generateToken(userDetails);
			//insertLoginLog(username);
		} catch (BadCredentialsException e) {
			LOGGER.warn("登录异常:{}", e.getMessage());
		}
		return token;
	}

	@Override
	public String refreshToken(String oldToken) {
		return jwtTokenUtil.refreshHeadToken(oldToken);
	}

	@Override
	public UmsAdmin getItem(Long id) {
		return adminMapper.selectByPrimaryKey(id);
	}

	@Override
	public List<UmsAdmin> list(String keyword, Integer pageSize, Integer pageNum) {
		PageHelper.startPage(pageNum, pageSize);
		UmsAdminExample example = new UmsAdminExample();
		UmsAdminExample.Criteria criteria = example.createCriteria();
		if (!StringUtils.isEmpty(keyword)) {
			criteria.andUsernameLike("%" + keyword + "%");
			example.or(example.createCriteria().andNickNameLike("%" + keyword + "%"));
		}
		return adminMapper.selectByExample(example);
	}

	@Override
	public int update(Long id, UmsAdmin admin) {
		admin.setId(id);
		UmsAdmin rawAdmin = adminMapper.selectByPrimaryKey(id);
		if(rawAdmin.getPassword().equals(admin.getPassword())){
			//与原加密密码相同的不需要修改
			admin.setPassword(null);
		}else{
			//与原加密密码不同的需要加密修改
			if(StrUtil.isEmpty(admin.getPassword())){
				admin.setPassword(null);
			}else{
				admin.setPassword(passwordEncoder.encode(admin.getPassword()));
			}
		}
		return adminMapper.updateByPrimaryKeySelective(admin);
	}

	@Override
	public int delete(Long id) {
		return adminMapper.deleteByPrimaryKey(id);
	}

	@Override
	public int updateRole(Long adminId, List<Long> roleIds) {
		int count = roleIds == null ? 0 : roleIds.size();
		//先删除原来的关系
		UmsAdminRoleRelationExample adminRoleRelationExample = new UmsAdminRoleRelationExample();
		adminRoleRelationExample.createCriteria().andAdminIdEqualTo(adminId);
		adminRoleRelationMapper.deleteByExample(adminRoleRelationExample);
		if (!CollectionUtils.isEmpty(roleIds)) {
			List<UmsAdminRoleRelation> list = new ArrayList<>();
			for (Long roleId : roleIds) {
				UmsAdminRoleRelation roleRelation = new UmsAdminRoleRelation();
				roleRelation.setAdminId(adminId);
				roleRelation.setRoleId(roleId);
				list.add(roleRelation);
			}
			adminRoleRelationDao.insertList(list);
		}
		return count;
	}

	@Override
	public List<UmsRole> getRoleList(Long adminId) {
		return adminRoleRelationDao.getRoleList(adminId);
	}

	@Override
	public UserDetails loadUserByUsername(String username){
		//获取用户信息
		UmsAdmin admin = getAdminByUsername(username);
		if (admin != null) {
			List<UmsResource> resourceList = getResourceList(admin.getId());
			return new AdminUserDetails(admin,resourceList);
		}
		throw new UsernameNotFoundException("用户名或密码错误");
	}

	@Override
	public UmsAdmin getAdminByUsername(String username) {
		UmsAdminExample example = new UmsAdminExample();
		example.createCriteria().andUsernameEqualTo(username);
		List<UmsAdmin> adminList = adminMapper.selectByExample(example);
		if (adminList != null && adminList.size() > 0) {
			return adminList.get(0);
		}
		return null;
	}

	@Override
	public List<UmsResource> getResourceList(Long adminId) {
		return adminRoleRelationDao.getResourceList(adminId);
	}

	@Override
	public int updatePermission(Long adminId, List<Long> permissionIds) {
		//修改权限需要先删除原来所有权限
		UmsAdminPermissionRelationExample relationExample = new UmsAdminPermissionRelationExample();
		relationExample.createCriteria().andAdminIdEqualTo(adminId);
		adminPermissionRelationMapper.deleteByExample(relationExample);
		//获取用户所有角色权限
		List<UmsPermission> permissionList = adminRoleRelationDao.getRolePermissionList(adminId);
		List<Long> rolePermissionList = permissionList.stream().map(UmsPermission::getId).collect(Collectors.toList());
		if (!CollectionUtils.isEmpty(permissionIds)) {
			List<UmsAdminPermissionRelation> relationList = new ArrayList<>();
			//筛选出+权限
			List<Long> addPermissionIdList = permissionIds.stream().filter(permissionId -> !rolePermissionList.contains(permissionId)).collect(Collectors.toList());
			//筛选出-权限
			List<Long> subPermissionIdList = rolePermissionList.stream().filter(permissionId -> !permissionIds.contains(permissionId)).collect(Collectors.toList());
			//插入+-权限关系
			relationList.addAll(convert(adminId,1,addPermissionIdList));
			relationList.addAll(convert(adminId,-1,subPermissionIdList));
			return adminPermissionRelationDao.insertList(relationList);
		}
		return 0;
	}

	private List<UmsAdminPermissionRelation> convert(Long adminId, Integer type, List<Long> permissionIdList) {
		List<UmsAdminPermissionRelation> relationList = permissionIdList.stream().map(permissionId -> {
			UmsAdminPermissionRelation relation = new UmsAdminPermissionRelation();
			relation.setAdminId(adminId);
			relation.setType(type);
			relation.setPermissionId(permissionId);
			return relation;
		}).collect(Collectors.toList());
		return relationList;
	}

	@Override
	public List<UmsPermission> getPermissionList(Long adminId) {
		return adminRoleRelationDao.getRolePermissionList(adminId);
	}

	@Override
	public int updatePassword(UpdateAdminPasswordParam  param) {

		if (StrUtil.isEmpty(param.getUsername())
			|| StrUtil.isEmpty(param.getOldPassword())
			||StrUtil.isEmpty(param.getNewPassword())){
			return -1;
		}
		UmsAdminExample example = new UmsAdminExample();
		example.createCriteria().andUsernameEqualTo(param.getUsername());
		List<UmsAdmin> adminList = adminMapper.selectByExample(example);
		if(CollUtil.isEmpty(adminList)){
			return -2;
		}
		UmsAdmin umsAdmin = adminList.get(0);
		if(!passwordEncoder.matches(param.getOldPassword(),umsAdmin.getPassword())){
			return -3;
		}
		umsAdmin.setPassword(passwordEncoder.encode(param.getNewPassword()));
		adminMapper.updateByPrimaryKey(umsAdmin);
		return 1;
	}
}
